package sessionBeans;

import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.xml.bind.JAXB;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

import org.hibernate.validator.internal.util.ModUtil;

import xml.RecibirSolicitudXML;
import xml.RespuestaXML;
import xml.SolicitudXML;
import dtos.ArticuloDTO;
import dtos.ModuloDTO;
import dtos.OrdenDespachoDTO;
import dtos.ServiciosModuloDTO;
import entities.Articulo;
import entities.EstadoOrdenDespacho;
import entities.EstadoOrdenDespachoValor;
import entities.EstadoSolicitud;
import entities.EstadoSolicitudValor;
import entities.Modulo;
import entities.OrdenDespacho;
import entities.ServiciosModulo;
import entities.Solicitud;
import exceptions.EntityAlreadyExistException;

/**
 * Session Bean implementation class AdministradorOrdenDespachoBean
 */
@Stateless
@LocalBean
public class AdministradorOrdenDespachoBean implements AdministradorOrdenDespacho {

	@PersistenceContext(unitName="CRM")
	private EntityManager em;
	
	@EJB
	private AdministradorSolicitud admSolic;
	
	@EJB
	private AdministradorMensajeria admMensajeria;
	
    public AdministradorOrdenDespachoBean() {
        // TODO Auto-generated constructor stub
    }
    

	@Override
	public void CargarOrdenDespacho(OrdenDespacho orden)
			throws EntityAlreadyExistException {
		
		OrdenDespacho od = this.buscarOrdenDespacho(orden.getCodigo(), orden.getPortal().getId());
		if(od != null){
			throw new EntityAlreadyExistException("Orden de Despacho:" + od.getCodigo());
		}
		try {
			/*ESTE METODO DEBE PROCESAR EL XML QUE LLEGA (QUE MANDA LOGISTICA)
			 * POR CADA ARTICULO SE DEBE OBTENER SU DEPOSITO Y PONERLO EN UN VECTOR
			 * DE MODULOS, ES DECIR, YO PIENSO, OBTENER TODOS LOS MODULOS DE DEPOSITO
			 * POR CADA MODULO, CREAR UN VECTOR Y OBTENER POR CADA UNO,
			 * TODOS LOS ARTICULOS QUE TIENE.
			 * UNA VEZ QUE SE OBTIENE, CREAR UNA SOLICITUD POR CADA DEPOSITO
			 */
			List<EstadoOrdenDespacho> listEstados = new ArrayList<EstadoOrdenDespacho>();
			EstadoOrdenDespacho est = new EstadoOrdenDespacho();
			est.setFecha(Calendar.getInstance().getTime());
			est.setValorEstado(EstadoOrdenDespachoValor.PENDIENTE_DE_ENTREGA.toString());
			listEstados.add(est);
			orden.setEstados(listEstados);
			//ord.set
			em.persist(orden);
		} catch (Exception e) {
//			logger.error("Error creando articulo nuevo");
			e.printStackTrace();
		}
	}

	@Override
	public List<OrdenDespachoDTO> GetAllOrdenesDespacho() {
		// TODO Auto-generated method stub
		Query q = em.createQuery("from OrdenDespacho");
		List<OrdenDespacho> listaOD = (ArrayList<OrdenDespacho>) q.getResultList();
		List<OrdenDespachoDTO> listOdDTO = new ArrayList<OrdenDespachoDTO>();
		for(OrdenDespacho ordsp : listaOD){
			OrdenDespachoDTO oddto = new OrdenDespachoDTO();
			oddto = oddto.parseDTO(ordsp);
			listOdDTO.add(oddto);
		}
		return listOdDTO;
	}

	@Override
	public OrdenDespacho buscarOrdenDespacho(String codigo, int portal) {
		// TODO Auto-generated method stub
		Query q = em.createQuery("from OrdenDespacho a where a.codigo = :codigo and a.portal.id = :portal");
		q.setParameter("codigo", codigo);
		q.setParameter("portal", portal);
		OrdenDespacho od = null;
		try {
			od = (OrdenDespacho) q.getSingleResult();
		} catch (NoResultException e) {
			// TODO: handle exception
			return od;
		}
		
		return od;
	}

	@Override
	public void CambiarEstadoOrdenDespacho(OrdenDespachoDTO orden) {
		// TODO Auto-generated method stub
		this.em.merge(orden);
	}

	
	@Override
	public RespuestaXML recibirSolicitudesJSON(RecibirSolicitudXML str)  {
		// TODO Auto-generated method stub
		//JSONObject json = (JSONObject) JSONSerializer.toJSON(str);
		RespuestaXML xml = new RespuestaXML();
		;
		int idSolicitud = Integer.parseInt(str.getIdSolicitud());
		if(idSolicitud != 0){
			Solicitud s = admSolic.buscarSolicitudAConfirmar(idSolicitud);
			
			if(s == null)
			{
				xml.setEstado("ERROR");
				xml.setMensaje("No existe la solicitud o su estado no es pendiente: " + str.getIdSolicitud());
				return xml;
			}
			
			EstadoSolicitud est = new EstadoSolicitud();
			est.setFecha(Calendar.getInstance().getTime());
			est.setNombre(EstadoSolicitudValor.CONFIRMADA.toString());
			s.addEstado(est);
			admSolic.CambiarEstadoSolicitud(s);
			this.ProcesoOrdenes(s);
			xml.setMensaje("OK");
			xml.setEstado("OK");
		}
		
		return xml;
	}

	public void ProcesoOrdenes(Solicitud s) {
		// TODO Auto-generated method stub
		
		OrdenDespacho orden = this.buscarOrdenDespachoByIdSolicitud(s.getId());
		boolean ordenListaParaDespachar = false;
		
		for (Solicitud sol : orden.getSolicitudes()) {
		
			EstadoSolicitud ultimoEstado = sol.getEstados().get(sol.getEstados().size() - 1);
			boolean solConfirmada = (ultimoEstado.getNombre().equals(EstadoSolicitudValor.CONFIRMADA.toString()));
			if(!solConfirmada)
			{
				return;
			}
		}
		
		this.admMensajeria.ConfirmarOrdenDeDespachoADespachar(orden);
	}
	
	private OrdenDespacho buscarOrdenDespachoByIdSolicitud(int idSolicitud)
	{
		Query q = em.createQuery("select o from OrdenDespacho o inner join o.solicitudes se where se.id = :idSolicitud");
		q.setParameter("idSolicitud", idSolicitud);
		OrdenDespacho orden = null;
		try {
			List<OrdenDespacho> lista = q.getResultList();
			if(!lista.isEmpty()){
				orden = lista.get(0);
			}
		} catch (Exception e) {
			// TODO: handle exception
			return orden;
		}
	return orden;
	}

}
